import numpy as np
import pylab as plt
from matplotlib.collections import *
import matplotlib.pyplot as mp
from mpl_toolkits.mplot3d import Axes3D
import mpl_toolkits.mplot3d as M3



from partie1 import *
from scipy.integrate import odeint


#------------------------#
#       projet 6         #
#                        #
#       partie 2         #
#------------------------#


#Modele Malthusien: b=naissances/N (taux de natalite)
#d=morts/N (taux de mortalite)
#gamma=(b-d)pourcentage de l'evolution



def malthus(gamma, h, t0, y0, N, meth):
    "resout l'equation du modele de Malthus avec la methode passee en entree"
    def f(y,t):
        return (gamma * y)
    return meth_n_step(y0, t0 , N , h , f , meth)


#kappa: capacite d'accueil
def verhulst(gamma, kappa, h, t0, y0, N, meth):
    "resout l'equation du modele de Verhulst"
    def f(y,t):
        return (gamma*y*(1-(y/kappa)))
    return meth_n_step(y0, t0, N, h, f, meth)



def lotka_volterra(a, b, c, d, t0, y0, h, N, meth):
    "resout le systeme de Lotka-Volterra"
    #y[0] -> N
    #y[1] -> P
    def f(y,t):
        if(y[0]<0):
            y[0]=0
        if(y[1]<0):
            y[1]=0
        return np.array([y[0]*(a-b*y[1]) , y[1]*(c*y[0]-d)])
    return meth_n_step(y0, t0, N, h, f, meth)

def lotka_volterra_2dim(a, b, c, d, t0, y0, h, N, meth, coul):
    "resout le systeme de Lotka-Volterra et affiche la variation du couple (N(t),P(t)) sur un plan"
    y = lotka_volterra(a, b, c, d, t0, y0, h, N, meth)
    mp.xlabel("proie")
    mp.ylabel("predateur")
    for i in range(len(y)):
        mp.plot([y[i][0]],[y[i][1]],coul)
    
    mp.show()



def lotka_volterra_3dim(a, b, c, d, t0, y0, h, N, meth):
    "resout le systeme de Lotka-Volterra et affiche la variation du couple (N(t),P(t)) en fonction du temps dans l'espace a 3 dimensions"
    y = lotka_volterra(a, b, c, d, t0, y0, h, N, meth)
    fig = plt.figure()
    ax = Axes3D(fig)
    y0= np.arange(len(y))
    y1= np.arange(len(y))
    for i in range(len(y)):
        y0[i] = y[i][0]
        y1[i] = y[i][1]
    t = np.linspace(0,100,len(y))
    ax.scatter(y0, y1, t)
    ax.set_xlabel("proie")
    ax.set_ylabel("predateurs")
    ax.set_zlabel("t")
    mp.show()


def pics(y):
    "genere la liste des maximums de la fonction representee par y"
    pic=np.zeros(len(y))
    j=0;
    for i in np.arange(1,len(y)-1,1):
        if((y[i][0]>= y[i-1][0]) and (y[i][0]>= y[i+1][0])):
            pic[j]=i
            j=j+1
    return (pic,j)



def periode(a, b, c, d, t0, y0, h, N, meth):
    "utilise la fonction pics pour calculer une valeur approchee de la periode de la fonction solution de lotka-volterra"
    y = lotka_volterra(a, b, c, d, t0, y0, h, N, meth)
    (tab_pics,j)=pics(y)
    p=0
    for i in np.arange(1, j, 1):
        p = p + tab_pics[i]-tab_pics[i-1]
    return (p/(j-1))
    

def local(a, b, c, d, t0, ylv0, h, N, pas, diff_max, meth):
    "affiche les graphes des fonctions solutions du systeme Lotka-Volterra en fonction du temps en faisant varier la condition initiale autour d'une valeur ylv0 et avec un pas pris en entree"
    for i in np.arange(0, diff_max, pas):
        y = lotka_volterra(a, b, c, d, t0, [i+ylv0[0],i+ylv0[1]], h, N, meth)
        x = np.linspace(0, 0.001, len(y))
        mp.plot(x,y, "k-")
        y = lotka_volterra(a, b, c, d, t0, [ylv0[0]-i, ylv0[1]-i], h, N, meth)
        x = np.linspace(0, 0.001, len(y))
        mp.plot(x,y, "k-")
    mp.xlabel("y(t)")
    mp.ylabel("t") 
    mp.show()


def local_2d(a, b, c, d, t0, ylv0, h, N, pas, diff_max, meth):
    "affiche les graphes de variations du couple (N(t),P(t)) solution du systeme Lotka-Volterra  dans le plan en faisant varier la condition initiale autour d'une valeur ylv0 et avec un pas pris en entree"
    pal=["b.","c.","m.","g.","k.","r.","y."]
    ind = 0
    for i in np.arange(0, diff_max, pas):
         y = lotka_volterra(a, b, c, d, t0, ylv0, h, N, meth)
         
         for j in range(len(y)):
             mp.plot([y[j][0]+i],[y[j][1]+i], pal[ind] )
         if (ind < 6 ):
             ind = ind + 1
         else:
             ind = 0
    mp.xlabel("proie")
    mp.ylabel("predateur")
    mp.show()

#Q8: Les points singuliers du systeme Lotka-Volterra sont les points qui verifient
#P(t)=a/b et N(t)=d/c


